﻿
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.IdentityModel.Tokens;
using Microsoft.OpenApi.Models;
using MySql.Data.MySqlClient;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Reflection;
using System.Security.Claims;
using System.Text;
using System.Text.Encodings.Web;
using System.Text.Unicode;
using System.Threading.Tasks;
using Tauren.File.Entity.Config;
using Tauren.File.Infrastructure;
using Tauren.File.Infrastructure.Filter;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using Newtonsoft.Json.Converters;
using Tauren.File.Entity.Const;

namespace Tauren.File.Core.ConfigExtension
{
    /// <summary>
    /// 注册服务
    /// </summary>
    public class RegisterServices
    {
        /// <summary>
        /// 进行服务注册
        /// </summary>
        public static void RegisterService(IServiceCollection services, IConfiguration configuration)
        {
            services.AddControllers(o =>
            {
                o.Filters.Add<IndetityServrAuthorize>();
                o.Filters.Add<SkipAttribute>();
            }).AddNewtonsoftJson(options =>
            {
                //修改时间的序列化方式
                options.SerializerSettings.Converters.Add(new IsoDateTimeConverter() { DateTimeFormat = GlobalConst.DATE_FORMAT_SECONDS });
                // 忽略循环引用
                options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
            });
            services.AddCors();
            ///添加json序列化         
            services.AddMvc(options => { options.Filters.Add(typeof(CustomExceptionFilter)); });
            ///添加数据中间件
            services.AddAutoMapper(Assembly.Load("Tauren.File.Mapper"));
            ///注册数据库链接Configure
            AddDBContext(services);

            services.AddSingleton(HtmlEncoder.Create(UnicodeRanges.All));

            ///配置jwt
            //AddJWTAuthorization(services);
            ////注入授权Handler
            //services.AddSingleton<IAuthorizationHandler, CustomAuthorize>();
            services.AddDistributedMemoryCache();

            services.AddSession(opt =>
            {
                opt.IdleTimeout = TimeSpan.FromMinutes(50);
            });
            SwaggerConfig.AddSwagger(services, configuration);
            ///注入Session服务
            services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
            ///注册数据库服务
            services.AddScoped<IDbConnection, MySqlConnection>();

            ///返回数据验证器数据
            services.Configure<ApiBehaviorOptions>(opt =>
            {
                opt.InvalidModelStateResponseFactory = actionContext =>
                {
                    //获取验证失败的模型字段 
                    var errors = actionContext.ModelState
                        .Where(e => e.Value.Errors.Count > 0)
                        .Select(e => new { field = e.Key, err = e.Value.Errors.Select(o => o.ErrorMessage) })
                        .ToList();
                    //设置返回内容
                    IResponseMessage result = new ResponseMessage
                    {
                        Status = false,
                        Message = "未通过数据验证",
                        Body = errors
                    };
                    return new BadRequestObjectResult(result);
                };
            }).AddHealthChecks();
            services.AddApiVersioning();
        }
        /// <summary>
        /// 添加数据库链接全局服务
        /// </summary>
        /// <param name="services"></param>
        public static void AddDBContext(IServiceCollection services)
        {
            ///获取数据连接
            var dbConnection = DBHelperExtension.GetDbBaseConnection();
            services.AddSingleton(dbConnection.my_write_connection);
        }
        /// <summary>
        /// 配置JWT授权
        /// </summary>
        /// <param name="services"></param>
        public static void AddJWTAuthorization(IServiceCollection services)
        {
            TokenHelper tokenHelper = new TokenHelperExtension().tokenHelper;
            var skey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(tokenHelper.TokenSecreKey));
            var signingCredentials = new SigningCredentials(skey, SecurityAlgorithms.HmacSha256);

            services.AddAuthorization(opt =>
            {
                var permissionRequirement = new CustomAauthorizeRequirement(ClaimTypes.Role, signingCredentials);
                opt.AddPolicy("CustomAuthorize", policy => policy.Requirements.Add(permissionRequirement));
            }).AddAuthentication(option =>
            {
                option.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                option.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;

            }).AddJwtBearer((jwtOptions) =>
            {
                jwtOptions.TokenValidationParameters = new TokenValidationParameters()
                {
                    ValidateIssuerSigningKey = true,
                    IssuerSigningKey = skey,
                    ValidateIssuer = true,
                    ValidIssuer = tokenHelper.Issuer,
                    ValidateAudience = true,
                    ValidAudience = tokenHelper.Audience,
                    ValidateLifetime = true,
                    ClockSkew = TimeSpan.Zero
                };
            });
        }
    }
}
